package com.baiwang.web.service;

import com.alibaba.fastjson.JSONObject;
import com.baiwang.web.common.properties.CommonProperties;
import com.baiwang.web.domain.*;
import com.baiwang.web.domain.vo.OutputInvoiceIssueVO;
import com.baiwang.web.handler.BaseException;
import com.baiwang.web.utils.BeanUtils;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.google.gson.Gson;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;
import java.io.*;
import java.net.URL;
import java.net.URLConnection;
import java.util.Arrays;
import java.util.Base64;
import java.util.List;
import java.util.UUID;
import static com.baiwang.web.common.enums.ExceptionInformation.ISSUANCEFAILED;
import static com.baiwang.web.common.enums.ExceptionInformation.ISSUEDSUCCESSFULLY;
import static com.baiwang.web.common.enums.ExceptionInformation.PDFPUSHFAILED;
import static com.baiwang.web.common.enums.ExceptionInformation.THEDOWNLOADISCOMPLETE;
import static com.baiwang.web.common.enums.ExceptionInformation.PDFINVOICEPUSHFAILED;
import static com.baiwang.web.common.enums.ExceptionInformation.PDFPUSHSUCCESS;
import static com.baiwang.web.common.enums.ExceptionInformation.POSTFAILED;

/**
 * @author zhanliuzhu
 * @date 2024/4/17
 */
@Slf4j
@Service
public class OutputInvoiceIssueServiceImpl implements OutputInvoiceIssueService {


    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private CommonProperties commonProperties;


    @Override
    @Transactional
    public Result issueInvoice(OutputInvoiceIssueVO invoiceIssueVO) throws JsonProcessingException, FileNotFoundException {

        // 一、调发票开具接口
        String postForObject = invoicing(invoiceIssueVO);

        // 二.判断接口调用成功失败
        String success = JSONObject.parseObject(postForObject).get("success").toString();
        if (success.equals("false")) {
            // 调用失败
            String message = JSONObject.parseObject(postForObject).get("message").toString();
            String errorMessage = JSONObject.parseObject(message).get("errorMessage").toString();
            log.info(ISSUANCEFAILED + "{}", errorMessage);
            return Result.error(errorMessage);

        } else {
            // 调用成功、调用浪潮两次接口
            log.info(ISSUEDSUCCESSFULLY);
            getOutputInvoiceIssueResponse(invoiceIssueVO, postForObject);
        }

        return Result.success();

    }

    @NotNull
    private void getOutputInvoiceIssueResponse(OutputInvoiceIssueVO invoiceIssueVO, String postForObject) throws JsonProcessingException, FileNotFoundException {

        // 一、开具是否开具成功
        String status = JSONObject.parseObject(postForObject).get("success").toString();
        if (status.equals("true")) {
            // 1.开具成功
            String model = JSONObject.parseObject(postForObject).get("model").toString();
            String success = JSONObject.parseObject(model).get("success").toString();

            // 2.将出参转换为 List对象集合
            Gson gson = new Gson();
            OutputInvoiceIssueInvoiceResult[] studentsArray = gson.fromJson(success, OutputInvoiceIssueInvoiceResult[].class);
            List<OutputInvoiceIssueInvoiceResult> responseList = Arrays.asList(studentsArray);

            // 3.遍历对象处理票据
            for (OutputInvoiceIssueInvoiceResult outputInvoiceIssueInvoiceResult : responseList) {
                // （1）.pdf保存本地 批量处理
                String pdfName = saveLocalPdf(outputInvoiceIssueInvoiceResult);

                // （2）.请求回调pdf上传接口
                uploadPdf(outputInvoiceIssueInvoiceResult, pdfName, invoiceIssueVO.getData());

                // （3）.请求浪潮回调发票参数接口
                pushMessages();
            }

        } else {
            //  todo 拆分开具失败返回拆分的发票金额明细信息
            String model = JSONObject.parseObject(postForObject).get("model").toString();
            String success = JSONObject.parseObject(model).get("success").toString();
            Gson gson = new Gson();
            InvoiceIssueInvoice[] studentsArray = gson.fromJson(success, InvoiceIssueInvoice[].class);


        }


    }

    /**
     * 推送票面信息到浪潮
     */
    private void pushMessages() {

        // 1.拼接url
        String url = commonProperties.getLangchaopushurl();

        // 2.构建请求体
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.add("Content-Type","text/xml;charset=utf-8");
        String entity = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
                "<soap:Envelope \n" +
                "    xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" \n" +
                "    xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" \n" +
                "    xmlns:targetNamespace=\"http://XSFPHX.org/\"\n" +
                "    xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">\n" +
                "    <soap:Body>\n" +
                "        <targetNamespace:XSFPHX xmlns=\"http://XSFPHX.org/\">\n" +
                "            <action></action>\n" +
                "            <json>{\"bhsj\":442.48,\"bmdm\":null,\"bz\":\"\",\"chyydm\":null,\"code\":null,\"czlx\":\"1\",\"czrydm\":null,\"daid\":null,\"details\":null,\"djbh\":\"BSF100112404080003\",\"djbhs\":null,\"djlx\":null,\"djmx\":null,\"drUrl\":null,\"dybz\":null,\"fhr\":null,\"fjys\":null,\"fpdm\":\"041002300111\",\"fphm\":\"31330299\",\"fpkjId\":null,\"fplxdm\":\"026\",\"fpqqlsh\":null,\"fprzztDm\":null,\"fpxx\":null,\"fpzt\":null,\"gdrq\":null,\"gdzt\":null,\"gflxfs\":null,\"ghdwdm\":null,\"ghdwdzdh\":null,\"ghdwmc\":null,\"ghdwyhzh\":null,\"gmfDh\":null,\"gmfDz\":null,\"gmfKhh\":null,\"gmfKhhzh\":null,\"gmfMc\":null,\"gmfNsrsbh\":null,\"gsdm\":\"10011\",\"hcczlx\":null,\"hckpfs\":null,\"hjje\":null,\"hsje\":500.0,\"htbh\":null,\"id\":null,\"je\":500.0,\"jshj\":500.0,\"jym\":null,\"jzzt\":0,\"khdh\":null,\"khdz\":null,\"khkhhmc\":null,\"khkhhzh\":null,\"kpddm\":null,\"kpfs\":\"\",\"kpr\":\"王一铭\",\"kprq\":\"2024-04-16\",\"kprq2\":null,\"kz1\":null,\"kz2\":null,\"kz3\":null,\"kz4\":null,\"kz6\":null,\"msg\":null,\"mxts\":null,\"nsrsbh\":\"91410000706784652H\",\"ofd\":null,\"orderId\":null,\"pzh\":null,\"qdbz\":null,\"qdfphm\":\"\",\"qmbz\":null,\"qmz\":null,\"scbz\":null,\"se\":57.52,\"sflzfp\":null,\"sfqdp\":null,\"sfwzp\":\"0\",\"sjlx\":\"2\",\"sjly\":\"1\",\"skm\":null,\"skr\":null,\"specialInfoJson\":null,\"sqdid\":\"79c274e585d14beca0fb8661cdab6912\",\"ssyf\":null,\"tdyslxDm\":null,\"tqm\":null,\"tspz\":\"00\",\"tzdh\":null,\"xfsytDm\":null,\"xhdwdm\":null,\"xhdwdzdh\":null,\"xhdwmc\":null,\"xhdwyhzh\":null,\"xml\":null,\"ydjbh\":null,\"yfpdm\":\"\",\"yfphm\":\"\",\"yfplx\":null,\"yhcje\":null,\"ykprq\":null,\"yqbz\":null,\"yqdfphm\":\"\",\"ywdid\":null,\"yxfphm\":\"31330299\",\"yxfpje\":500.0,\"yxfpse\":57.52,\"zdydjbh\":null,\"zfdqsj\":null,\"zfr\":null,\"zfrq\":null,\"zhsl\":null,\"zsfs\":\"0\",\"zsxhdwmc\":null,\"zsxhdwsbh\":null,\"zyspmc\":null,\"zzjgdm\":\"814f887e24944295a03df07c05272bc2\",\"zzsytDm\":null}</json>\n" +
                "            <message></message>\n" +
                "        </targetNamespace:XSFPHX>\n" +
                "    </soap:Body>\n" +
                "</soap:Envelope>" ;
        HttpEntity<String> request = new HttpEntity<>(entity, httpHeaders);

        String post = null;
        try {
            // 3.发送请求
            post = restTemplate.postForObject(url, request, String.class);
        } catch (RestClientException e) {
            new BaseException(POSTFAILED+e.getMessage());
        }
        if (!post.contains("\"ReMessage\":\"接受成功\"")){
            log.info("{}" + POSTFAILED, post);
            throw new BaseException(POSTFAILED);
        }
    }


    /**
     * 请求回调pdf上传接口
     */
    private void uploadPdf(OutputInvoiceIssueInvoiceResult outputInvoiceIssueInvoiceResult, String pdfName, InvoiceIssueDetailData invoiceIssueDetailData) {
        // 1.回调接口返回pdf文件
        String base64String = "";
        try {
            // 读取PDF文件
            File file = new File(pdfName);
            FileInputStream fileInputStream = new FileInputStream(file);
            byte[] bytes = new byte[(int) file.length()];
            fileInputStream.read(bytes);
            fileInputStream.close();

            // 将文件内容转换为Base64字符串
            base64String = Base64.getEncoder().encodeToString(bytes);
            // System.out.println("Base64值: " + base64String);

        } catch (Exception e) {
            e.printStackTrace();
        }

        // 2.发送POST请求到回调接口-pdf上传
        String url = commonProperties.getLangchaopushpdf();
        HttpHeaders headers = new HttpHeaders();
        headers.add("Content-Type", "text/xml");

        String xmlInput = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
                "<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">\n" +
                "  <soap:Body>\n" +
                "    <ImageInterfaceService xmlns=\"http://PaperPark.WebService/WebInterface\">\n" +
                "      <param><![CDATA[<?xml version=\"1.0\" encoding=\"UTF-8\"?><params><safety><clientcode>WB</clientcode><servicecode>" + invoiceIssueDetailData.getDrawer() + "</servicecode><time>" + System.currentTimeMillis() + "</time><ticket>20140712161833ImageCenterWB</ticket></safety><serverbody><servername>SENDIMAGE</servername><servertype></servertype><services><service><barcode>" + outputInvoiceIssueInvoiceResult.getInvoiceNo() + "</barcode><filename>" + pdfName + "</filename><ifhx>0</ifhx><content>" + base64String + "</content></service></services></serverbody></params>]]></param>\n" +
                "    </ImageInterfaceService>\n" +
                "  </soap:Body>\n" +
                "</soap:Envelope>";

        HttpEntity<String> request = new HttpEntity<>(xmlInput, headers);

        String postForObject = null;
        try {
            postForObject = restTemplate.postForObject(url, request, String.class);
        } catch (RestClientException e) {
            log.info("{}" + PDFPUSHFAILED, e.getMessage());
            throw new BaseException(PDFPUSHFAILED + e.getMessage());
        }

        // 推动pdf失败的处理逻辑
        if (!postForObject.contains("&lt;result&gt;0&lt;/result&gt;")) {
            log.info("{}" + PDFPUSHFAILED, postForObject);
            throw new BaseException(PDFPUSHFAILED + postForObject);
        } else {
            log.info("{}" + PDFPUSHSUCCESS, postForObject);
        }


    }

    /**
     * pdf保存本地
     */
    private String saveLocalPdf(OutputInvoiceIssueInvoiceResult result) throws FileNotFoundException {

        String pdfName = commonProperties.getPdfurl() + UUID.randomUUID() + ".pdf";
        FileOutputStream out = new FileOutputStream(pdfName); // 指定下载后保存的文件名

        // 保存到本地
        try {
            URL urlResult = new URL(result.getEInvoiceUrl().toString());
            URLConnection conn = urlResult.openConnection();
            InputStream in = conn.getInputStream();

            byte[] buffer = new byte[1024];
            int bytesRead;
            while ((bytesRead = in.read(buffer)) != -1) {
                out.write(buffer, 0, bytesRead);
            }

            out.close();
            in.close();

            log.info("{}" + THEDOWNLOADISCOMPLETE, pdfName);
        } catch (IOException e) {
            throw new BaseException(PDFINVOICEPUSHFAILED);
        }
        return pdfName;
    }

    @Nullable
    private String invoicing(OutputInvoiceIssueVO invoiceIssueVO) {

        // 1.拼接url
        String url = commonProperties.getBaiwnagurl() + UUID.randomUUID();

        // 2.参数补充
        InvoiceIssueDO invoiceIssueDO = BeanUtils.toBean(invoiceIssueVO, InvoiceIssueDO.class);
        invoiceIssueDO.setFormatGenerate(true);

        // 3.发送请求
        String postForObject = null;
        try {
            postForObject = restTemplate.postForObject(url, invoiceIssueDO, String.class);
        } catch (RestClientException e) {
            log.info(PDFINVOICEPUSHFAILED + "{}", e.getMessage());
            throw new BaseException(PDFINVOICEPUSHFAILED);
        }
        return postForObject;
    }
}
